home *** CD-ROM | disk | FTP | other *** search
- # Source Generated with Decompyle++
- # File: in.pyc (Python 2.6)
-
- import os
- import sys
- import pickle
- import random as rand
- import gobject
- gobject.threads_init()
- import pygst
- pygst.require('0.10')
- import gst
- import utils
- from pygobject import gsignal
- import sources
- from leveller import Leveller
-
- class Jukebox(gst.Bin):
- gsignal('done', str)
- gsignal('prerolled')
- gsignal('changed', str, gobject.TYPE_UINT64)
- gsignal('looped')
-
- def __init__(self, files, rms = 0.2, loops = 0, random = False, caps = 'audio/x-raw-int,channels=2,rate=44100', picklepath = 'level.pck'):
- self.__gobject_init__()
- self._target_rms = rms
- self._loopsleft = loops
- self._loopsdone = 0
- self._random = random
- self._picklepath = picklepath
- self._caps = gst.caps_from_string(caps)
- self._files = files[:]
- self._levels = { }
- self._prerolled = False
- self._playing = False
- self._scani = 0
- self._playi = 0
- self._lastadded = None
- self._lastposition = long(0)
- if not len(files) > 1:
- raise TypeError, 'Must have at least 2 files'
- len(files) > 1
- self._composition = gst.element_factory_make('gnlcomposition')
- self._composition.connect('pad-added', self._composition_pad_added_cb)
- self.add(self._composition)
- self._srcpad = None
- if os.path.exists(self._picklepath):
- file = open(self._picklepath)
- self._levels = pickle.load(file)
- file.close()
-
- if self._random:
- self._files = rand.sample(self._files, len(self._files))
-
-
-
- def preroll(self):
- gst.debug('starting jukebox prerolling')
- self._scan()
-
-
- def start(self):
- if not self._prerolled:
- raise Exception, 'baby'
- self._prerolled
- self.set_state(gst.STATE_PAUSED)
-
-
- def _scan(self):
- if self._scani >= len(self._files):
- gst.debug("We're done scanning !")
- return None
- file = self._files[self._scani]
- self._scani += 1
- if file in self._levels.keys():
- gst.debug('already did file %s' % file)
- self._check_prerolled()
- gobject.timeout_add(0, self._scan)
- return None
- gst.debug('creating leveller for %s' % file)
- leveller = Leveller(file)
- leveller.connect('done', self._leveller_done_cb, file)
- gobject.timeout_add(0, leveller.start)
-
-
- def _leveller_done_cb(self, l, reason, file):
- if reason != sources.EOS:
- gst.debug('Error: %s' % reason)
- return None
- gst.debug('in: %s, out: %s' % (gst.TIME_ARGS(l.mixin), gst.TIME_ARGS(l.mixout)))
- gst.debug('rms: %f, %f dB' % (l.rms, l.rmsdB))
- self._levels[file] = (l.rms, l.mixin, l.mixout, l.length)
- gst.debug('writing level pickle')
- file = open(self._picklepath, 'w')
- pickle.dump(self._levels, file)
- file.close()
- self._check_prerolled()
- self._scan()
- gobject.timeout_add(0, l.clean)
-
-
- def _new_gnl_source(self, location, start):
- '''
- Creates a new GnlSource containing an AudioSource with the following
- properties correctly set:
- _ volume level
- _ priority
- _ duration
- The start position MUST be given
- '''
- if not self._levels[location]:
- return None
- self.debug('Creating new GnlSource at %s for %s' % (gst.TIME_ARGS(start), location))
- idx = self._files.index(location) + self._loopsdone * len(self._files)
- (rms, mixin, mixout, duration) = self._levels[location]
- gnls = gst.element_factory_make('gnlsource', 'source-%d-%s' % (idx, location))
- src = sources.AudioSource(location)
- gnls.add(src)
- level = 1
- if rms > self._target_rms:
- level = self._target_rms / rms
- gst.debug('setting volume of %f' % level)
- else:
- gst.debug('not going to go above 1.0 level')
- src.set_volume(level)
- gnls.props.priority = 2 * self._loopsdone + 1 + idx % 2
- gnls.props.start = long(start)
- gnls.props.duration = long(duration)
- gnls.props.media_duration = long(duration)
- gnls.props.media_start = long(0)
- return gnls
-
-
- def _new_mixer(self, start, duration):
- gnlo = gst.element_factory_make('gnloperation')
- ad = gst.element_factory_make('adder')
- gnlo.add(ad)
- gnlo.props.sinks = 2
- gnlo.props.start = start
- gnlo.props.duration = duration
- gnlo.props.priority = 0
- return gnlo
-
-
- def _append_file(self, location):
- '''
- Appends the given file to the composition, along with the proper mixer effect
- '''
- self.debug('location:%s' % location)
- start = self._lastposition
- if self._lastadded:
- start += self._levels[self._lastadded][2]
- start -= self._levels[location][1]
-
- gnls = self._new_gnl_source(location, start)
- self._composition.add(gnls)
- if self._lastadded:
- duration = (self._levels[self._lastadded][3] - self._levels[self._lastadded][2]) + self._levels[location][1]
- mixer = self._new_mixer(start, duration)
- self._composition.add(mixer)
-
- self._lastposition = start
- self._lastadded = location
- self.debug('lastposition:%s , lastadded:%s' % (gst.TIME_ARGS(self._lastposition), self._lastadded))
-
-
- def _check_prerolled(self):
- gst.debug('_check_prerolled: index: scan %d, play %d' % (self._scani, self._playi))
- if not (self._prerolled) and self._scani > self._playi + 1:
- self._prerolled = True
- self._append_file(self._files[0])
- self._append_file(self._files[1])
- self.debug('now prerolled and ready to play')
- self.emit('prerolled')
-
-
-
- def _emit_changed(self, file, when):
- print 'emitting changed for %s at %r' % (file, when)
- self.emit('changed', file, when)
-
-
- def _source_clean(self, source):
- source.set_state(gst.STATE_NULL)
- self.remove(source)
- source.clean()
-
-
- def _composition_pad_added_cb(self, comp, pad):
- if self._srcpad:
- return None
- self.debug('Ghosting source pad %s' % pad)
- self._srcpad = gst.GhostPad('src', pad)
- self._srcpad.set_active(True)
- self.add_pad(self._srcpad)
-
-
- def do_handle_message(self, message):
- self.debug('got message %s / %s / %r' % (message.src.get_name(), message.type.first_value_name, message))
- gst.Bin.do_handle_message(self, message)
-
-
- def do_state_change(self, transition):
- if not self._prerolled:
- gst.error('Call Jukebox.preroll() before!')
- return gst.STATE_CHANGE_FAILURE
- return gst.Bin.do_state_change(self, message)
-
-
- gobject.type_register(Jukebox)
-
- def _find_elements_recurse(element):
- if not isinstance(element, gst.Bin):
- return [
- element]
- l = []
- for e in element.elements():
- l.extend(_find_elements_recurse(e))
-
- return l
-
-
- def _find_unconnected_pad(bin, direction):
- for e in _find_elements_recurse(bin):
- for p in e.pads():
- if p.get_direction() == direction and not p.get_peer():
- return p
-
-
-
- if __name__ == '__main__':
- main = gobject.MainLoop()
- pipeline = gst.Pipeline('jukebox')
- list = open(sys.argv[1]).read().rstrip().split('\n')
- print list
- source = Jukebox(list, random = True, loops = 1)
-
- def _jukebox_prerolled_cb(jukebox):
- print 'prerolled'
- _start()
-
-
- def _jukebox_changed_cb(jukebox, filename, when):
- print 'changed file to %s at %s' % (filename, float(when) / gst.TIME_ARGS(gst.SECOND))
-
-
- def _jukebox_looped_cb(jukebox):
- print 'jukebox looped'
-
-
- def _start():
- source.start()
- print 'setting pipeline to PLAYING'
- pipeline.set_state(gst.STATE_PLAYING)
- print 'set pipeline to PLAYING'
-
-
- def jukebox_pad_added(comp, pad, sinkpad):
- pad.link(sinkpad)
-
-
- def jukebox_message(bus, message):
- if message.type == gst.MESSAGE_ERROR:
- print 'Error: %s' % message.parse_error()
- main.quit()
- elif message.type == gst.MESSAGE_EOS:
- print 'done'
- main.quit()
-
-
- source.connect('prerolled', _jukebox_prerolled_cb)
- source.connect('changed', _jukebox_changed_cb)
- source.connect('looped', _jukebox_looped_cb)
- source.preroll()
- pipeline.add(source)
- bus = pipeline.get_bus()
- bus.add_signal_watch()
- bus.connect('message', jukebox_message)
- p = 'alsasink'
- if len(sys.argv) > 2:
- p = ' '.join(sys.argv[2:])
-
- print 'parsing output pipeline %s' % p
- sinkbin = gst.parse_launch('bin.( %s )' % p)
- pipeline.add(sinkbin)
- apad = _find_unconnected_pad(sinkbin, gst.PAD_SINK)
- if not apad:
- raise TypeError, 'No unconnected sink pad found in bin %r' % sinkbin
- apad
- sinkpad = gst.GhostPad('sink', apad)
- sinkbin.add_pad(sinkpad)
- source.connect('pad-added', jukebox_pad_added, sinkpad)
- print 'Going into main loop'
- sys.stdout.flush()
- main.run()
- print 'Left main loop'
- sys.stdout.flush()
- pipeline.set_state(gst.STATE_NULL)
-
-